package com.zzh.camera2.permission

import android.Manifest
import android.annotation.TargetApi
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import android.widget.Toast
import java.util.*

/**
 * @author ：zuhui.zhang
 * time ： 2021/4/29 10:52
 */
object PermissionCheckUtil {
    private const val TAG = "PermissionCheckUtil"

    // 此处列出所有需要的权限
    val ALL_PERMISSIONS = arrayOf(
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CAMERA
    )

    // 此处列出必要的权限
    val REQUIRED_PERMISSIONS = arrayOf(
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CAMERA
    )
    const val PREVIOUS_ACTIVITY_INTENT = "previous_intent"
    const val MISSING_PERMISSIONS = "missing_permissions"
    var sPermissionsActivityStarted = 0

    // 请求所有权限时调用
    fun requestAllPermissions(activity: Activity): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) requestPermissions(
            activity,
            ALL_PERMISSIONS
        ) else true
    }

    // 请求必要权限时调用
    fun requestRequiredPermissions(activity: Activity): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) requestPermissions(
            activity,
            REQUIRED_PERMISSIONS
        ) else true
    }

    private fun requestPermissions(activity: Activity, permissions: Array<String>): Boolean {
        val missingList = getMissingPermissions(activity, permissions)
        return requestPermissions(activity, missingList)
    }

    fun getMissingPermissions(
        activity: Activity, requiredPermissions: Array<String>
    ): ArrayList<String> {
        val missingList = ArrayList<String>()
        for (i in requiredPermissions.indices) {
            if (!hasPermission(activity, requiredPermissions[i])) {
                missingList.add(requiredPermissions[i])
            }
        }
        return missingList
    }

    fun hasNeverGrantedPermissions(activity: Activity, permissionList: ArrayList<String>): Boolean {
        var isNeverGranted = false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            for (i in permissionList.indices) {
                if (isNeverGrantedPermission(activity, permissionList[i])) {
                    isNeverGranted = true
                    Log.d(
                        TAG, " hasNeverGrantedPermissions "
                                + permissionList[i] + " is always denied"
                    )
                    break
                }
            }
        }
        return isNeverGranted
    }

    @TargetApi(Build.VERSION_CODES.M)
    fun isNeverGrantedPermission(activity: Activity, permission: String?): Boolean {
        return !activity.shouldShowRequestPermissionRationale(permission!!)
    }

    private fun requestPermissions(activity: Activity, missingList: ArrayList<String>): Boolean {
        if (missingList.size == 0) {
            Log.d(TAG, " requestPermissions all permissions granted")
            return true
        }
        val missingArray = arrayOfNulls<String>(missingList.size)
        missingList.toArray(missingArray)
        val intentPermissions = Intent(activity, PermissionCheckActivity::class.java)
        intentPermissions.putExtra(PREVIOUS_ACTIVITY_INTENT, activity.intent)
        intentPermissions.putExtra(MISSING_PERMISSIONS, missingArray)
        activity.startActivity(intentPermissions)
        activity.finish()
        return false
    }

    fun checkAllPermissions(context: Context): Boolean {
        return checkPermissions(context, ALL_PERMISSIONS)
    }

    fun checkRequiredPermissions(context: Context): Boolean {
        return checkPermissions(context, REQUIRED_PERMISSIONS)
    }

    private fun checkPermissions(context: Context, permissions: Array<String>): Boolean {
        for (permission in permissions) {
            if (!hasPermission(context, permission)) {
                Log.d(TAG, "checkPermissions false : $permission")
                return false
            }
        }
        return true
    }

    fun onRequestPermissionsResult(
        activity: Activity, requestCode: Int, permissions: Array<String>,
        grantResults: IntArray?, needFinish: Boolean
    ): Boolean {
        for (i in permissions.indices) {
            if (!hasPermission(activity, permissions[i])) {
                var isNeverGrantedPermission = false
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    isNeverGrantedPermission = isNeverGrantedPermission(activity, permissions[i])
                }
                // Show toast
                if (isRequiredPermission(permissions[i]) || isNeverGrantedPermission) {
                    showNoPermissionsToast(activity)
                    if (needFinish) {
                        activity.finish()
                    }
                }
                Log.d(TAG, "onRequestPermissionsResult return false")
                return false
            }
        }
        val requiredPermissions: Array<String>
        requiredPermissions = REQUIRED_PERMISSIONS
        for (i in requiredPermissions.indices) {
            if (!hasPermission(activity, requiredPermissions[i])) {
                var isNeverGrantedPermission = false
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    isNeverGrantedPermission = isNeverGrantedPermission(activity, permissions[i])
                }
                // Show toast
                if (isRequiredPermission(requiredPermissions[i]) || isNeverGrantedPermission) {
                    if (!isPermissionChecking()) {
                        showNoPermissionsToast(activity)
                    }
                    if (needFinish) {
                        activity.finish()
                    }
                }
                Log.d(TAG, "onRequestPermissionsResult return false")
                return false
            }
        }
        Log.d(TAG, "onRequestPermissionsResult return true")
        return true
    }

    fun hasPermission(context: Context, permission: String?): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) hasPermissionForM(
            context,
            permission
        ) else true
    }

    @TargetApi(Build.VERSION_CODES.M)
    fun hasPermissionForM(context: Context, permission: String?): Boolean {
        return context.checkSelfPermission(permission!!) == PackageManager.PERMISSION_GRANTED
    }

    fun showNoPermissionsToast(context: Context?) {
        Toast.makeText(context, "has some permission not granted", Toast.LENGTH_LONG).show()
    }

    fun isPermissionChecking(): Boolean {
        Log.d(TAG, " isPermissionChecking Activity Count: " + sPermissionsActivityStarted)
        return sPermissionsActivityStarted > 0
    }

    /*
     * It means permission activity would be finished if startActivity is false.
     */
    fun setPermissionActivityCount(startActivity: Boolean) {
        if (startActivity) {
            if (sPermissionsActivityStarted < 0) {
                sPermissionsActivityStarted = 0
            }
            sPermissionsActivityStarted++
        } else {
            sPermissionsActivityStarted--
            if (sPermissionsActivityStarted < 0) {
                sPermissionsActivityStarted = 0
            }
        }
        Log.d(
            TAG, "setPermissionActivityCount: "
                    + sPermissionsActivityStarted + ", start: " + startActivity
        )
    }

    fun isRequiredPermission(permission: String): Boolean {
        val requiredPermissions: Array<String>
        requiredPermissions = REQUIRED_PERMISSIONS
        for (i in requiredPermissions.indices) {
            if (requiredPermissions[i] == permission) {
                Log.d(TAG, "isRequiredPermission: $permission")
                return true
            }
        }
        return false
    }
}